package cn.com.acca.ma.dao.impl;

import cn.com.acca.ma.dao.ModelStockAnalysisDao;
import cn.com.acca.ma.hibernate.util.HibernateUtil;
import cn.com.acca.ma.jdbctemplate.impl.WriteModelStockAnalysisByDateTransactionCallback;
import cn.com.acca.ma.jdbctemplate.util.JdbcTemplateUtil;
import cn.com.acca.ma.jpa.util.JpaUtil;
import cn.com.acca.ma.model.ModelStockAnalysis;
import cn.com.acca.ma.model.ModelTopStock;
import java.sql.CallableStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.Query;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.CallableStatementCallback;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import javax.persistence.EntityManager;

public class ModelStockAnalysisDaoImpl extends BaseDaoImpl<ModelStockAnalysis> implements
    ModelStockAnalysisDao {

    public ModelStockAnalysisDaoImpl() {
        super();
    }

    /**
     * 计算MDL_STOCK_ANALYSIS表的全部数据
     */
    @Override
    public void writeModelStockAnalysis() {
        logger.info("开始计算MDL_STOCK_ANALYSIS表的全部数据");

        transactionTemplate = JdbcTemplateUtil.getTransactionTemplate();
        jdbcTemplate = JdbcTemplateUtil.getJdbcTemplate();

        transactionTemplate.execute(new TransactionCallback<Object>() {
            @Override
            public Object doInTransaction(TransactionStatus transactionStatus) {
                try {
                    jdbcTemplate
                        .execute("{call PKG_MODEL_STOCK_ANALYSIS.write_mdl_stock_analysis}");
                } catch (Throwable e) {
                    transactionStatus.setRollbackOnly();
                    // transactionStatus.rollbackToSavepoint(savepoint);
                }
                return null;
            }
        });
    }

    /**
     * 根据开始时间beginDate和结束时间endDate，从表MDL_STOCK_ANALYSIS中获取DATE_字段
     * @param beginDate
     * @param endDate
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<Date> getDateByCondition(String beginDate, String endDate){
        logger.info("根据开始时间【" + beginDate + "】和结束时间【" + endDate + "】，"
            + "从表MDL_STOCK_ANALYSIS中获取DATE_字段");

        StringBuffer hql = new StringBuffer("select distinct t.date from ModelStockAnalysis t " +
            "where t.date between to_date(?,'yyyy-mm-dd') and to_date(?,'yyyy-mm-dd')");
        session = HibernateUtil.currentSession();
        session.beginTransaction();
        Query query = session.createQuery(hql.toString());
        query.setParameter(0, beginDate);
        query.setParameter(1, endDate);
        List<Date> list = query.list();
        session.getTransaction().commit();
        session.close();

        return list;
    }

    /**
     * 计算MDL_STOCK_ANALYSIS表的某一日的数据
     *
     * @param multithreading
     * @param date
     */
    @Override
    public void writeModelStockAnalysisByDate(boolean multithreading, String date) {
        logger.info("开始计算MDL_STOCK_ANALYSIS表的某一日【" + date + "】的数据");

        TransactionTemplate newTransactionTemplate = null;
        JdbcTemplate newJdbcTemplate = null;
        if (multithreading) {
            newTransactionTemplate = JdbcTemplateUtil.newTransactionTemplate();
            newJdbcTemplate = JdbcTemplateUtil.newJdbcTemplate();
            WriteModelStockAnalysisByDateTransactionCallback writeModelStockAnalysisByDateTransactionCallback = new WriteModelStockAnalysisByDateTransactionCallback(newJdbcTemplate, date);
            newTransactionTemplate.execute(writeModelStockAnalysisByDateTransactionCallback);
        } else {
            transactionTemplate = JdbcTemplateUtil.getTransactionTemplate();
            jdbcTemplate = JdbcTemplateUtil.getJdbcTemplate();
            WriteModelStockAnalysisByDateTransactionCallback writeModelStockAnalysisByDateTransactionCallback = new WriteModelStockAnalysisByDateTransactionCallback(jdbcTemplate, date);
            transactionTemplate.execute(writeModelStockAnalysisByDateTransactionCallback);
        }
    }

    /**
     * 从表MDL_STOCK_ANALYSIS中获取date日的所有ModelStockAnalysis对象
     * @param date
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<ModelStockAnalysis> getModelStockAnalysisByDate(String date){
        logger.info("从表MDL_STOCK_ANALYSIS中获取日期【" + date + "】的所有ModelStockAnalysis对象");

        StringBuffer hql = new StringBuffer("select t from ModelStockAnalysis t " +
            "where t.date=to_date(?,'yyyy-mm-dd') order by t.date asc");
        session = HibernateUtil.currentSession();
        session.beginTransaction();
        Query query = session.createQuery(hql.toString());
        query.setParameter(0, date);
        List<ModelStockAnalysis> list=query.list();
        session.getTransaction().commit();
        session.close();

        return list;
    }

    /**
     * 向表MDL_STOCK_ANALYSIS中插入ModelStockAnalysis对象
     * @param modelStockAnalysis
     */
    public void save(ModelStockAnalysis modelStockAnalysis){
        logger.info("向表MDL_STOCK_ANALYSIS中插入ModelStockAnalysis对象");

        session = HibernateUtil.currentSession();
        session.beginTransaction();
        session.persist(modelStockAnalysis);
        session.getTransaction().commit();
        session.close();
    }

    /**
     * 根据开始时间和结束时间，计算每个交易日、所有股票的平均收盘价和平均方差，并按时间升序排列
     *
     * @param beginDate
     * @param endDate
     * @return
     */
    public List<Object> findAverageClosePriceAndAverageStandardDeviationByBeginDateAndEndDateOrderByDate(String beginDate, String endDate) {
        logger.info("开始根据开始时间【" + beginDate + "】和结束时间【" + endDate + "】，" +
                "计算每个交易日、所有股票的平均收盘价，并按时间升序排列");

        String queryClose = new String(
                "select avg(stda.close_price), avg(msa.standard_deviation), max(stda.close_price), min(stda.close_price)," +
                        "max(msa.standard_deviation), min(msa.standard_deviation), stda.date_ " +
                        "from stock_transaction_data_all stda " +
                        "join mdl_stock_analysis msa on msa.code_=stda.code_ and msa.date_=stda.date_ and msa.standard_deviation is not null " +
                        "where stda.date_ between to_date('" + beginDate + "','yyyy-mm-dd') and to_date('" + endDate + "','yyyy-mm-dd') " +
                        "group by stda.date_ order by stda.date_ asc");

        EntityManager entityManager = null;
        em = JpaUtil.currentEntityManager();
        em.getTransaction().begin();
        javax.persistence.Query query = em.createNativeQuery(queryClose);

        List<Object> list = query.getResultList();

        em.getTransaction().commit();
        em.close();

        return list;
    }
}
